#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
解析 data.json 文件并生成解密版的 JSON
"""

import json
import os
import sys
import argparse
from pathlib import Path
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import padding
from cryptography.hazmat.backends import default_backend
import base64

# 默认 token
DEFAULT_TOKEN = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMTUyNjA2MCIsImlzcyI6IiIsImlhdCI6MTc1NTY4MjYxMiwibmJmIjoxNzU2MjgyMzU5LCJleHAiOjE5MTM5NjIzNTl9.NsPM71zygG1zPtM5-GN5xTZmCfaDT_GTLYboINIVnF8"


def vp(enc_data: str, token: str = DEFAULT_TOKEN) -> dict:
    """
    vp 解密函数

    Args:
        enc_data: 加密的数据
        token: 用于解密的 token

    Returns:
        解密后的数据字典，失败时返回 None
    """
    try:
        # 提取密钥：token 的第 2-18 位
        key = token[2:18]

        if len(key) != 16:
            raise ValueError(f"密钥长度错误: {len(key)}, 期望: 16")

        # 将密钥转换为字节
        key_bytes = key.encode('utf-8')

        # 解码 Base64 数据
        encrypted_data = base64.b64decode(enc_data)

        # 创建 AES-CBC 解密器
        cipher = Cipher(
            algorithms.AES(key_bytes),
            modes.CBC(key_bytes),  # IV 使用与密钥相同的值
            backend=default_backend()
        )
        decryptor = cipher.decryptor()

        # 解密数据
        decrypted_data = decryptor.update(encrypted_data) + decryptor.finalize()

        # 去除 PKCS7 填充
        unpadder = padding.PKCS7(128).unpadder()
        unpadded_data = unpadder.update(decrypted_data) + unpadder.finalize()

        # 解析 JSON
        decrypted_text = unpadded_data.decode('utf-8')
        if not decrypted_text:
            raise ValueError('解密结果为空')

        return json.loads(decrypted_text)

    except Exception as error:
        print(f'解密失败: {error}')
        return None


def parse_data_json(file_path: str, token: str = DEFAULT_TOKEN) -> dict:
    """
    解析 data.json 文件

    Args:
        file_path: data.json 文件路径
        token: 用于解密的 token

    Returns:
        解密后的完整响应对象，失败时返回 None
    """
    try:
        print(f'正在读取文件: {file_path}')

        # 读取文件
        with open(file_path, 'r', encoding='utf-8') as f:
            content = f.read()
            data = json.loads(content)

        print('原始响应结构:')
        print(f'- code: {data.get("code")}')
        print(f'- msg: {data.get("msg")}')
        print(f'- encData: {"存在" if data.get("encData") else "不存在"}')

        if not data.get("encData"):
            print('没有找到 encData 字段，返回原始数据')
            return data

        print('\n开始解密 encData...')
        print(f'encData 长度: {len(data["encData"])}')

        # 解密 encData
        decrypted_data = vp(data["encData"], token)

        if decrypted_data is None:
            print('解密失败')
            return None

        # 构建解密后的响应对象
        result = {
            "code": data["code"],
            "msg": data["msg"],
            "data": decrypted_data
        }

        print('\n解密成功！')
        data_type = type(decrypted_data).__name__
        print(f'解密后数据类型: {data_type}')

        if isinstance(decrypted_data, list):
            print(f'数组长度: {len(decrypted_data)}')

        return result

    except Exception as error:
        print(f'解析文件失败: {error}')
        return None


def save_decrypted_data(data: dict, output_path: str):
    """
    保存解密后的数据

    Args:
        data: 解密后的数据
        output_path: 输出文件路径
    """
    try:
        json_string = json.dumps(data, ensure_ascii=False, indent=2)

        # 确保输出目录存在
        output_dir = Path(output_path).parent
        output_dir.mkdir(parents=True, exist_ok=True)

        with open(output_path, 'w', encoding='utf-8') as f:
            f.write(json_string)

        print(f'\n解密后的数据已保存到: {output_path}')
        print(f'文件大小: {len(json_string) / 1024:.2f} KB')

    except Exception as error:
        print(f'保存文件失败: {error}')


def show_data_summary(data: dict):
    """
    显示解密数据的摘要信息

    Args:
        data: 解密后的数据
    """
    if not data or 'data' not in data:
        print('没有数据可显示')
        return

    print('\n=== 解密数据摘要 ===')

    decrypted_data = data['data']

    if isinstance(decrypted_data, list):
        print(f'数据类型: 数组')
        print(f'数组长度: {len(decrypted_data)}')

        if decrypted_data:
            print('\n前几项数据预览:')
            for i, item in enumerate(decrypted_data[:3]):
                print(f'\n第 {i + 1} 项:')
                for key, value in item.items():
                    if isinstance(value, str) and len(value) > 50:
                        display_value = value[:50] + '...'
                    else:
                        display_value = value
                    print(f'  {key}: {display_value}')

            if len(decrypted_data) > 3:
                print(f'\n... 还有 {len(decrypted_data) - 3} 项数据')

    elif isinstance(decrypted_data, dict):
        print(f'数据类型: 对象')
        print(f'对象键数量: {len(decrypted_data)}')

        print('\n对象结构预览:')
        for i, (key, value) in enumerate(list(decrypted_data.items())[:10]):
            if isinstance(value, str) and len(value) > 50:
                display_value = value[:50] + '...'
            else:
                display_value = value
            print(f'  {key}: {display_value}')

        if len(decrypted_data) > 10:
            print(f'  ... 还有 {len(decrypted_data) - 10} 个键')

    else:
        print(f'数据类型: {type(decrypted_data).__name__}')
        print(f'数据值: {decrypted_data}')


def main():
    """主函数"""
    parser = argparse.ArgumentParser(description='解析 data.json 文件并解密')
    parser.add_argument('-f', '--file', default='./data.json', help='指定 data.json 文件路径 (默认: ./data.json)')
    parser.add_argument('-t', '--token', default=DEFAULT_TOKEN, help='指定解密用的 token (默认: 内置 token)')
    parser.add_argument('-o', '--output', help='指定输出文件路径 (默认: 不保存文件)')

    args = parser.parse_args()

    # 检查文件是否存在
    if not os.path.exists(args.file):
        print(f'文件不存在: {args.file}')
        return

    print('=== 开始解析 data.json ===\n')

    # 解析文件
    result = parse_data_json(args.file, args.token)

    if not result:
        print('解析失败')
        return

    # 显示摘要信息
    show_data_summary(result)

    # 保存文件（如果指定了输出路径）
    if args.output:
        save_decrypted_data(result, args.output)
    else:
        # 默认保存到同目录下的 decrypted_data.json
        default_output_path = Path(args.file).parent / 'decrypted_data.json'
        save_decrypted_data(result, str(default_output_path))

    print('\n=== 解析完成 ===')


if __name__ == '__main__':
    main()
